using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;

using SBPweb.Themes.Windows;
using SBPweb.Themes.Windows.Skins;

namespace SBPweb.Controls.Windows.Tab
{
	/// <summary>
	/// Class of TabPane
	/// </summary>
	[ToolboxItem(false)]
	public partial class TabPane : System.Windows.Forms.Control, ISkinnable
	{
		#region Private members

		private bool mUseDefaultSkin;
		private Skin mSkin;
		private Margin mSizingMargin;
		private Margin mContentMargin;
		private MouseEventState mMState = MouseEventState.None;
		private TabPage mTabPage;
		private SizeF size;

		#endregion

		#region Constructor logic

		/// <summary>
		/// Constructor of TabPane
		/// </summary>
		/// <param name="tabPage">tabpage</param>
		public TabPane(TabPage tabPage)
		{
			mTabPage = tabPage;

			SetStyle();
			InitializeComponent();
			InitializeSkin();
			RegisterEventHandlers();
		}

		/// <summary>
		/// Constructor of TabPane
		/// </summary>
		/// <param name="tabPage">tabpage</param>
		/// <param name="skin">skin</param>
		public TabPane(TabPage tabPage, Skin skin)
		{
			mTabPage = tabPage;
			mSkin = skin;
			
			SetStyle();
			InitializeComponent();
			InitializeSkin();
			RegisterEventHandlers();
		}

		private void SetStyle()
		{
			base.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true);
		}

		private void RegisterEventHandlers()
		{
			this.MouseClick += new MouseEventHandler(this_MouseClick);
			this.MouseEnter += new EventHandler(this_MouseEnter);
			this.MouseLeave += new EventHandler(this_MouseLeave);
			this.MouseDown += new MouseEventHandler(this_MouseDown);
			this.MouseUp += new MouseEventHandler(this_MouseUp);
			this.MouseHover += new EventHandler(this_MouseHover);
			if (mTabPage != null)
			{
				mTabPage.TextChanged += new EventHandler(Parent_TextChanged);
			}
			DefaultLookAndFeel.OnSkinChanged += new EventHandler(DefaultLookAndFeel_OnSkinChanged);
		}

		private void InitializeSkin()
		{
			if(Skin == null)
			{
				this.mContentMargin = new Margin();
				this.mSizingMargin = new Margin();
			}
			else
			{
				this.mContentMargin = Skin.CachedProperties.TabHeaderContentMargin;
				this.mSizingMargin = Skin.CachedProperties.TabHeaderSizingMargin;
			}
			if (mTabPage != null)
			{
				this.Text = mTabPage.Text;
			}
		}

		#endregion

		#region Custom draw

		/// <summary>
		/// OnPaint
		/// </summary>
		/// <param name="e">event args</param>
		protected override void OnPaint(PaintEventArgs e)
		{
			if (Skin == null)
			{
				base.OnPaint(e);
				return;
			}

			System.Drawing.Image img = Skin.CachedProperties.TabHeaderImage;
			bool verticalLayout = Skin.CachedProperties.TabHeaderLayout == LayoutDirection.Vertical;

			int imgCount = 5;
			int imgWidth = img.Width;
			int imgHeight = (Int32)(img.Height / imgCount);
			int imgTop;
			int imgLeft;

			if (!verticalLayout)
			{
				imgWidth = (Int32)(img.Width / imgCount);
				imgHeight = img.Height;
				imgTop = 0;

				switch (mMState)
				{
					default:
					case MouseEventState.None:
						if (this.Enabled)
						{
							imgLeft = 0;
						}
						else
						{
							imgLeft = 3 * imgWidth;
						}
						if (this.Selected)
						{
							imgTop = 2 * imgHeight;
						}
						break;
					case MouseEventState.OnHover:
						imgLeft = 1 * imgWidth;
						break;
					case MouseEventState.OnDown:
						if (this.Enabled)
						{
							imgLeft = 2 * imgWidth;
						}
						else
						{
							imgLeft = 4 * imgWidth;
						}
						break;
				}
			}
			else
			{
				imgLeft = 0;
				switch (mMState)
				{
					default:
					case MouseEventState.None:
						if (this.Enabled)
						{
							imgTop = 0;
						}
						else
						{
							imgTop = 3 * imgHeight;
						}
						if (this.Selected)
						{
							imgTop = 2 * imgHeight;
						}
						break;
					case MouseEventState.OnHover:
						imgTop = 1 * imgHeight;
						break;
					case MouseEventState.OnDown:
						if (this.Enabled)
						{
							imgTop = 2 * imgHeight;
						}
						else
						{
							imgTop = 4 * imgHeight;
						}
						break;
				}
			}

			#region Image parts
			Rectangle iLT = new Rectangle(imgLeft, imgTop, mSizingMargin.Left, mSizingMargin.Top);
			Rectangle iT = new Rectangle(imgLeft + mSizingMargin.Left, imgTop, imgWidth - mSizingMargin.Horizontal, mSizingMargin.Top);
			Rectangle iRT = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop, mSizingMargin.Right, mSizingMargin.Top);
			Rectangle iLM = new Rectangle(imgLeft, imgTop + mSizingMargin.Top, mSizingMargin.Left, (imgHeight - 1) - mSizingMargin.Vertical);
			Rectangle iM = new Rectangle(imgLeft + mSizingMargin.Left, imgTop + mSizingMargin.Top, imgWidth - mSizingMargin.Horizontal, (imgHeight - 1) - mSizingMargin.Vertical);
			Rectangle iRM = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop + mSizingMargin.Top, mSizingMargin.Right, (imgHeight - 1) - mSizingMargin.Vertical);
			Rectangle iLB = new Rectangle(imgLeft, imgTop + imgHeight - mSizingMargin.Bottom, mSizingMargin.Left, mSizingMargin.Bottom);
			Rectangle iB = new Rectangle(imgLeft + mSizingMargin.Left, imgTop + imgHeight - mSizingMargin.Bottom, imgWidth - mSizingMargin.Horizontal, mSizingMargin.Bottom);
			Rectangle iRB = new Rectangle(imgLeft + imgWidth - mSizingMargin.Right, imgTop + imgHeight - mSizingMargin.Bottom, mSizingMargin.Right, mSizingMargin.Bottom);
			#endregion

			#region Window parts
			Rectangle tLT = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Top, mSizingMargin.Left, mSizingMargin.Top);
			Rectangle tT = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Top, this.ClientRectangle.Width - mSizingMargin.Horizontal, mSizingMargin.Top);
			Rectangle tRT = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Top, mSizingMargin.Right, mSizingMargin.Top);
			Rectangle tLM = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Top + mSizingMargin.Top, mSizingMargin.Left, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tM = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Top + mSizingMargin.Top, this.ClientRectangle.Width - mSizingMargin.Horizontal, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tRM = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Top + mSizingMargin.Top, mSizingMargin.Right, this.ClientRectangle.Height - mSizingMargin.Vertical);
			Rectangle tLB = new Rectangle(this.ClientRectangle.Left, this.ClientRectangle.Bottom - mSizingMargin.Bottom, mSizingMargin.Left, mSizingMargin.Bottom);
			Rectangle tB = new Rectangle(this.ClientRectangle.Left + mSizingMargin.Left, this.ClientRectangle.Bottom - mSizingMargin.Bottom, this.ClientRectangle.Width - mSizingMargin.Horizontal, mSizingMargin.Bottom);
			Rectangle tRB = new Rectangle(this.ClientRectangle.Right - mSizingMargin.Right, this.ClientRectangle.Bottom - mSizingMargin.Bottom, mSizingMargin.Right, mSizingMargin.Bottom);
			#endregion

			#region Drawing
			e.Graphics.DrawImage(img, tLT, iLT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tT, iT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRT, iRT, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tLM, iLM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tM, iM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRM, iRM, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tLB, iLB, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tB, iB, GraphicsUnit.Pixel);
			e.Graphics.DrawImage(img, tRB, iRB, GraphicsUnit.Pixel);

			DrawText(e);
			#endregion
		}

		/// <summary>
		/// On background paint 
		/// </summary>
		/// <param name="e">event args</param>
		protected override void OnPaintBackground(PaintEventArgs e)
		{
			base.OnPaintBackground(e);
		}

		private void DrawText(PaintEventArgs e)
		{
			StringFormat sf = new StringFormat(StringFormat.GenericDefault);
			size = e.Graphics.MeasureString(this.Text, this.Font, new Point(0, 0), sf);
			this.MinimumSize = new System.Drawing.Size((int)size.Width + mContentMargin.Horizontal, (int)size.Height + mContentMargin.Vertical);

			float xLeft, xCenter, xRight, yTop, yMiddle, yBottom;
			float textX, textY;

			int canvasWidth = this.ClientRectangle.Width - mContentMargin.Horizontal;
			int canvasHeight = this.ClientRectangle.Height - mContentMargin.Vertical;

			xLeft = mContentMargin.Left;
			xCenter = (canvasWidth - size.Width) / 2 + mContentMargin.Left;
			xRight = canvasWidth - size.Width + mContentMargin.Right;

			yTop = mContentMargin.Top;
			yMiddle = (canvasHeight - size.Height) / 2 + mContentMargin.Top;
			yBottom = (canvasHeight - size.Height) + mContentMargin.Bottom;

			textX = xCenter;
			textY = yMiddle;

			e.Graphics.TextRenderingHint = Skin.TextRenderingHint;
			if (this.Enabled)
			{
				e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(Skin.CachedProperties.ControlTextColor), new RectangleF(textX, textY, textX + size.Width, textY + size.Height));
			}
			else
			{
				e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(Skin.CachedProperties.ControlDisabledTextColor), new RectangleF(textX, textY, textX + size.Width, textY + size.Height));
			}
		}
		#endregion

		#region Properties

		/// <summary>
		/// Is selected?
		/// </summary>
		public bool Selected
		{
			get
			{
				return (mTabPage.Parent as TabControl).SelectedTab == mTabPage;
			}
			set
			{
				if (value)
				{
					TabControl tc = mTabPage.Parent as TabControl;
					tc.SelectedTab = mTabPage;
					this.BringToFront();
					tc.Parent.Invalidate(true);
				}
			}
		}

		#endregion

		#region Events

		private void this_MouseClick(object sender, MouseEventArgs e)
		{
			Selected = true;
		}

		private void this_MouseEnter(object sender, EventArgs e)
		{
			mMState = MouseEventState.OnHover;
			this.Invalidate();
		}

		private void this_MouseUp(object sender, MouseEventArgs e)
		{
			mMState = MouseEventState.None;
			this.Invalidate();
		}

		private void this_MouseDown(object sender, MouseEventArgs e)
		{
			mMState = MouseEventState.OnDown;
			this.Invalidate();
		}

		private void this_MouseLeave(object sender, EventArgs e)
		{
			mMState = MouseEventState.None;
			this.Invalidate();
		}

		private void this_MouseHover(object sender, EventArgs e)
		{
			mMState = MouseEventState.OnHover;
		}

		private void DefaultLookAndFeel_OnSkinChanged(object sender, EventArgs e)
		{
			InitializeSkin();
		}

		private void Parent_TextChanged(object sender, EventArgs e)
		{
			this.Text = mTabPage.Text;
		}

		#endregion

		#region ISkinnable Members

		/// <summary>
		/// Use default skin?
		/// </summary>
		[Category("Look && feel")]
		public bool UseDefaultSkin
		{
			get
			{
				return mUseDefaultSkin;
			}
			set
			{
				mUseDefaultSkin = value;
				Invalidate();
			}
		}

		/// <summary>
		/// Used skin
		/// </summary>
		[Category("Look && feel")]
		public Skin Skin
		{
			get
			{
				if (this.UseDefaultSkin)
				{
					return DefaultLookAndFeel.Skin;
				}

				return mSkin;
			}
			set
			{
				mSkin = value;
				Invalidate();
			}
		}

		#endregion
	}
}
